<template>
  <div class="node-editor" ref="editorRef" @contextmenu.prevent="showContextMenu" @wheel="handleWheel" @mousemove="handleMouseMove"
    @mouseup="handleMouseUp" @mousedown="handleMouseDown" :style="{ cursor: isSpaceDown ? 'grab' : 'default' }">
    <!-- 保存按钮 -->
    <div class="save-button-container">
      <div class="save-button" @click="handleSave">保存</div>
    </div>

    <!-- 缩放控制组 -->
    <div class="zoom-control-container">
      <div class="zoom-button" @click="handleResetZoom">原始大小</div>
      <div class="zoom-button" @click="handleZoomIn">放大</div>
      <div class="zoom-display">{{ Math.round(scale * 100) }}%</div>
      <div class="zoom-button" @click="handleZoomOut">缩小</div>
    </div>

    <!-- 节点编辑器容器 -->
    <div v-if="contextMenu.visible" class="context-menu"
      :style="{ left: `${contextMenu.x}px`, top: `${contextMenu.y}px` }">
      <div class="menu-item" @click="$event => createNode('procedure', $event)">新建节点</div>
    </div>

    <!-- 画布容器，应用缩放变换 -->
    <div class="canvas-container" :style="canvasStyle">
      <!-- 连接线渲染 -->
      <Connection v-for="connection in connections" :key="connection.id" :connection="connection"
        :sourceNode="findNodeById(connection.source)" :targetNode="findNodeById(connection.target)"
        @select="handleConnectionSelect" />

      <!-- 节点渲染 -->
      <Node v-for="node in nodes" :key="node.id" :node="node" :is-selected="selectedNode && selectedNode.id === node.id"
        @select="handleNodeSelect" @update:position="updateNodePosition" @connection-created="handleConnectionCreated"
        @connection-drag-start="handleConnectionDragStart" @connection-drag-end="handleConnectionDragEnd" />
    </div>

    <!-- 连线预览组件 - 放在最外层确保最高层级 -->
    <ConnectionPreview :visible="isDraggingConnection" :startX="connectionStartX" :startY="connectionStartY"
      :endX="connectionEndX" :endY="connectionEndY" />
      
    <!-- 操作指南组件 -->
    <NodeEditorHelp />
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, provide } from 'vue';
import Node from './Node.vue';
import Connection from './Connection.vue';
import ConnectionPreview from './ConnectionPreview.vue';
import NodeEditorHelp from './NodeEditorHelp.vue';

// 添加对编辑器DOM元素的引用
const editorRef = ref(null);
const nodes = ref([]);
const connections = ref([]);
const contextMenu = ref({
  visible: false,
  x: 0,
  y: 0
});
const draggingNode = ref(null);
const dragOffsetX = ref(0);
const dragOffsetY = ref(0);
const selectedNode = ref(null);
const selectedConnection = ref(null);
const draggingSourceNode = ref(null);
const draggingSourcePortIndex = ref(-1);
const isDraggingConnection = ref(false);
const connectionStartX = ref(0);
const connectionStartY = ref(0);
const connectionEndX = ref(0);
const connectionEndY = ref(0);
const scale = ref(1);
const translateX = ref(0);
const translateY = ref(0);
const isSpaceDown = ref(false);
const isLeftMouseDown = ref(false);
const dragStartX = ref(0);
const dragStartY = ref(0);
const isDragging = ref(false);

// 提供给子组件的值 - 确保提供的是响应式引用
provide('draggingSourceNode', draggingSourceNode);
provide('draggingSourcePortIndex', draggingSourcePortIndex);
provide('scale', scale);
provide('translateX', translateX);
provide('translateY', translateY);

const canvasStyle = computed(() => {
  return {
    transform: `translate(${translateX.value}px, ${translateY.value}px) scale(${scale.value})`,
    transformOrigin: '0 0'
  };
});

function handleNodeSelect(node) {
  selectedNode.value = node;
  selectedConnection.value = null;
}

function handleConnectionSelect(connection) {
  if (selectedConnection.value) {
    selectedConnection.value.selected = false;
  }
  selectedConnection.value = connection;
  if (connection) {
    connection.selected = true;
  }
  selectedNode.value = null;
}

function findNodeById(nodeId) {
  return nodes.value.find(node => node.id === nodeId);
}

function showContextMenu(e) {
  e.stopPropagation();
  contextMenu.value = {
    visible: true,
    x: e.clientX,
    y: e.clientY
  };
}

function hideContextMenu() {
  contextMenu.value.visible = false;
}

function handleGlobalClick(e) {
  const contextMenuEl = document.querySelector('.context-menu');
  if (contextMenuEl && !contextMenuEl.contains(e.target)) {
    hideContextMenu();
  }

  const nodeEl = e.target.closest('.node');
  const connectionEl = e.target.closest('.line-selected');
  if (!nodeEl) {
    selectedNode.value = null;
  }
  if (!connectionEl) {
    if (selectedConnection.value) {
      connections.value.filter(conn => {
        if (selectedConnection.value && conn.id === selectedConnection.value.id) {
          conn.selected = false;
        }
      });
      selectedConnection.value.selected = false;
      selectedConnection.value = null;
    }
  }

  isDragging.value = false;
}

function handleMouseDown(e) {
  if (isSpaceDown.value && e.button === 0) {
    isLeftMouseDown.value = true;
    dragStartX.value = e.clientX;
    dragStartY.value = e.clientY;
    isDragging.value = false;

    document.body.style.cursor = 'grabbing';
    e.preventDefault();
  }
}

function handleMouseMove(e) {
  if (isSpaceDown.value && isLeftMouseDown.value) {
    isDragging.value = true;

    const deltaX = e.clientX - dragStartX.value;
    const deltaY = e.clientY - dragStartY.value;

    translateX.value += deltaX;
    translateY.value += deltaY;

    dragStartX.value = e.clientX;
    dragStartY.value = e.clientY;
  }

  if (isDraggingConnection.value) {
    // 使用ref引用获取DOM元素，而不是依赖e.currentTarget
    const editorRect = editorRef.value ? editorRef.value.getBoundingClientRect() : { left: 0, top: 0 };

    connectionEndX.value = (e.clientX - editorRect.left - translateX.value) / scale.value;
    connectionEndY.value = (e.clientY - editorRect.top - translateY.value) / scale.value;
  }
}

function handleMouseUp(e) {
  if (e.button === 0 && isLeftMouseDown.value) {
    isLeftMouseDown.value = false;
    isDragging.value = false;

    document.body.style.cursor = isSpaceDown.value ? 'grab' : 'default';
  }
  if (isDraggingConnection.value) {
    handleConnectionDragEnd();
  }
}

function createNode(type, event) {
  const config = {
    type: 'procedure',
    title: '过程节点',
    inputs: [{ type: 'exec', name: '输入', x: 0, y: 0 }, { type: 'exec', name: '输入', x: 0, y: 0 }],
    outputs: [{ type: 'exec', name: '输出', x: 0, y: 0 }, { type: 'exec', name: '输出', x: 0, y: 0 }]
  };
  // 使用ref引用获取DOM元素，而不是依赖event.currentTarget
  const editorRect = editorRef.value ? editorRef.value.getBoundingClientRect() : { left: 0, top: 0 };
  const canvasX = (contextMenu.value.x - editorRect.left - translateX.value) / scale.value;
  const canvasY = (contextMenu.value.y - editorRect.top - translateY.value) / scale.value;

  const nodeConfig = {
    ...config,
    x: canvasX,
    y: canvasY
  };

  addNode(nodeConfig);
  hideContextMenu();
}

function addNode(node) {
  const newNode = {
    ...node,
    id: Date.now().toString(),
    x: node.x,
    y: node.y,
    width: node.width || 150,
    height: node.height || 100
  };
  nodes.value.push(newNode);

  console.log('节点创建:', {
    id: newNode.id,
    type: newNode.type,
    position: { x: newNode.x, y: newNode.y },
    size: { width: newNode.width, height: newNode.height },
    inputs: newNode.inputs,
    outputs: newNode.outputs
  });
}

function removeNode(nodeId) {
  nodes.value = nodes.value.filter(node => node.id !== nodeId);
  connections.value = connections.value.filter(
    conn => conn.source !== nodeId && conn.target !== nodeId
  );
}

function removeConnection(connectionId) {
  connections.value = connections.value.filter(
    conn => conn.id !== connectionId
  );
}

function validateConnection(connection) {
  const { source, sourcePortIndex, target, targetPortIndex } = connection;
  if (source === target) return false;
  const sourceNode = findNodeById(source);
  const targetNode = findNodeById(target);

  const sourcePort = sourceNode.outputs[sourcePortIndex];
  const targetPort = targetNode.inputs[targetPortIndex];
  const isPortValid = sourcePort?.type === targetPort?.type;

  const existing = connections.value.find(
    conn => conn.source === source &&
      conn.sourcePortIndex === sourcePortIndex &&
      conn.target === target &&
      conn.targetPortIndex === targetPortIndex
  );

  return isPortValid && !existing;
}

function handleConnectionCreated({ source, sourcePortIndex, target, targetPortIndex, targetPortPosition }) {
  const connection = {
    source,
    sourcePortIndex,
    target,
    targetPortIndex
  };
  console.log('连接创建:', connection);
  if (validateConnection(connection)) {
    const sourceNode = findNodeById(source);
    const targetNode = findNodeById(target);

    if (targetNode && targetNode.inputs[targetPortIndex] && targetPortPosition) {
      targetNode.inputs[targetPortIndex].x = targetPortPosition.x;
      targetNode.inputs[targetPortIndex].y = targetPortPosition.y;
    }

    connections.value.push({
      id: `${source}-${sourcePortIndex}-${target}-${targetPortIndex}`,
      selected: false,
      ...connection
    });
  }
  draggingSourceNode.value = null;
}

function handleKeyDown(e) {
  if (e.key === 'Delete') {
    if (selectedNode.value) {
      removeNode(selectedNode.value.id);
      selectedNode.value = null;
    } else if (selectedConnection.value) {
      removeConnection(selectedConnection.value.id);
      selectedConnection.value = null;
    }
  }

  if (e.key === ' ' && !isSpaceDown.value) {
    isSpaceDown.value = true;
    document.body.style.cursor = isLeftMouseDown.value ? 'grabbing' : 'grab';
  }
}

function handleKeyUp(e) {
  if (e.key === ' ') {
    isSpaceDown.value = false;
    document.body.style.cursor = 'default';

    if (isLeftMouseDown.value) {
      isLeftMouseDown.value = false;
      isDragging.value = false;
    }
  }
}

function updateNodePosition({ id, position, portPositions }) {
  console.log('updateNodePosition called with:', { id, position, portPositions });
  const node = nodes.value.find(n => n.id === id);
  if (node) {
    node.x = position.x;
    node.y = position.y;

    if (portPositions) {
      node.inputs.forEach((input, index) => {
        if (portPositions.inputs[index]) {
          input.x = portPositions.inputs[index].x;
          input.y = portPositions.inputs[index].y;
        }
      });

      node.outputs.forEach((output, index) => {
        if (portPositions.outputs[index]) {
          output.x = portPositions.outputs[index].x;
          output.y = portPositions.outputs[index].y;
        }
      });
    }

    console.log('节点移动:', {
      id: node.id,
      type: node.type,
      position: { x: node.x, y: node.y },
      inputs: node.inputs,
      outputs: node.outputs
    });
  }
}

function handleWheel(e) {
  e.preventDefault();

  const rect = e.currentTarget.getBoundingClientRect();
  const mouseX = e.clientX - rect.left;
  const mouseY = e.clientY - rect.top;

  const mouseXInCanvas = (mouseX - translateX.value) / scale.value;
  const mouseYInCanvas = (mouseY - translateY.value) / scale.value;

  const delta = e.deltaY > 0 ? -0.05 : 0.05;
  const newScale = Math.max(0.1, Math.min(2, scale.value + delta));

  const newTranslateX = mouseX - mouseXInCanvas * newScale;
  const newTranslateY = mouseY - mouseYInCanvas * newScale;

  scale.value = newScale;
  translateX.value = newTranslateX;
  translateY.value = newTranslateY;
}

function handleConnectionDragStart({ sourceNode, sourcePortIndex, startX, startY }) {
  isDraggingConnection.value = true;
  // 创建一个新的对象引用，确保响应式更新
  draggingSourceNode.value = {...sourceNode};
  draggingSourcePortIndex.value = sourcePortIndex;
  connectionStartX.value = startX;
  connectionStartY.value = startY;
  connectionEndX.value = startX;
  connectionEndY.value = startY;

  // 打印日志以便调试
  console.log('开始拖拽连接线:', {
    sourceNodeId: sourceNode.id,
    sourcePortIndex: sourcePortIndex,
    startPosition: { x: startX, y: startY }
  });

  const node = nodes.value.find(n => n.id === sourceNode.id);
  if (node && node.outputs[sourcePortIndex]) {
    node.outputs[sourcePortIndex].x = startX;
    node.outputs[sourcePortIndex].y = startY;
  }

  document.addEventListener('mousemove', handleMouseMove);
  document.addEventListener('mouseup', handleMouseUp);
}

function handleConnectionDragEnd() {
  isDraggingConnection.value = false;
  draggingSourceNode.value = null;
  draggingSourcePortIndex.value = -1;
}

function handleResetZoom() {
  scale.value = 1;
}

function handleZoomIn() {
  scale.value = Math.min(2, scale.value + 0.1);
}

function handleZoomOut() {
  scale.value = Math.max(0.1, scale.value - 0.1);
}

function handleSave() {
  const editorState = {
    canvas: {
      scale: scale.value,
      translateX: translateX.value,
      translateY: translateY.value
    },
    nodes: nodes.value.map(node => ({
      id: node.id,
      type: node.type,
      title: node.title,
      x: node.x,
      y: node.y,
      width: node.width,
      height: node.height,
      inputs: node.inputs,
      outputs: node.outputs
    })),
    connections: connections.value.map(conn => {
      const sourceNode = findNodeById(conn.source);
      const targetNode = findNodeById(conn.target);
      const sourcePort = sourceNode.outputs[conn.sourcePortIndex];
      const targetPort = targetNode.inputs[conn.targetPortIndex];

      return {
        id: conn.id,
        source: conn.source,
        sourcePortIndex: conn.sourcePortIndex,
        sourcePort: {
          type: sourcePort.type,
          name: sourcePort.name,
          x: sourcePort.x,
          y: sourcePort.y
        },
        target: conn.target,
        targetPortIndex: conn.targetPortIndex,
        targetPort: {
          type: targetPort.type,
          name: targetPort.name,
          x: targetPort.x,
          y: targetPort.y
        },
        configValue: conn.configValue
      };
    })
  };

  console.log('节点编辑器状态：', JSON.stringify(editorState, null, 2));
}

onMounted(() => {
  document.addEventListener('click', handleGlobalClick);
  document.addEventListener('keydown', handleKeyDown);
  document.addEventListener('keyup', handleKeyUp);
});

onBeforeUnmount(() => {
  document.removeEventListener('click', handleGlobalClick);
  document.removeEventListener('keydown', handleKeyDown);
  document.removeEventListener('keyup', handleKeyUp);
});
</script>

<style>
@import '../assets/styles/NodeEditor.css';
</style>